using net_work.Common.Request;
using net_work.Common.Result;
using net_work.Data.DTO.Appr;
using net_work.Data.Entity.Appr;
using net_work.Data.Enum.Appr;
using net_work.Data.VO.Appr;
using net_work.IRepository.Appr;
using net_work.IRepository.Sys;
using net_work.IService.Appr;

namespace net_work.Service.Appr;

public class FlowNodeService(
    IFlowNodeRepository flowNodeRepository,
    IDepartmentRepository departmentRepository,
    ITeacherRepository teacherRepository)
    : IFlowNodeService
{
    public Task<PagedResult<FlowNodeResult>> GetFlowNodesPagedAsync(PagedRequest request)
    {
        return flowNodeRepository.GetFlowNodePagedAsync(request);
    }

    public Task<FlowNode?> SelectByIdAsync(long flowNodeId)
    {
        return flowNodeRepository.GetByIdAsync(flowNodeId);
    }

    public async Task<long> InsertFlowNode(FlowNodeAddRequest flowNodeAddRequest)
    {
        var total = 0;
        switch (flowNodeAddRequest.ProcessingType)
        {
            case NodeProcessingType.Dept:
                var department = await departmentRepository.GetByIdAsync(flowNodeAddRequest.ProcessingId);
                if (department == null)
                {
                    return -1;
                }

                var teacherPagedAsync = await teacherRepository.GetTeacherPagedAsync(new PagedRequest(1,
                    PageSizeEnum.Unlimited,
                    [new FilterCondition("DepId", FilterOperator.Equals, flowNodeAddRequest.ProcessingId)]));
                total = teacherPagedAsync.TotalRecords;

                break;
            case NodeProcessingType.Teacher:
                var teacher = await teacherRepository.GetByIdAsync(flowNodeAddRequest.ProcessingId);
                if (teacher == null)
                {
                    return -1;
                }

                total = 1;
                break;
            default:
                throw new ArgumentOutOfRangeException($"无效的属性名: {flowNodeAddRequest.ProcessingType}");
        }

        switch (flowNodeAddRequest.SuccessType)
        {
            case NodeSuccessType.OnlyOne:
                break;
            case NodeSuccessType.All:
                break;
            case NodeSuccessType.Number:
                if (flowNodeAddRequest.SuccessConfig is not > 0)
                {
                    return -1;
                }

                if (flowNodeAddRequest.SuccessConfig.Value > total)
                {
                    return -1;
                }

                break;
            case NodeSuccessType.PCT:
                if (flowNodeAddRequest.SuccessConfig is not > 0)
                {
                    return -1;
                }

                if (flowNodeAddRequest.SuccessConfig > 100)
                {
                    return -1;
                }

                break;
            default:
                throw new ArgumentOutOfRangeException($"无效的属性名: {flowNodeAddRequest.SuccessType}");
        }

        if (flowNodeAddRequest.SuccessNodeId != null && flowNodeAddRequest.SuccessNodeId.Value != -1)
        {
            var successNode = await flowNodeRepository.GetByIdAsync(flowNodeAddRequest.SuccessNodeId.Value);
            if (successNode == null)
            {
                return -1;
            }
        }

        if (flowNodeAddRequest.FailureNodeId != null && flowNodeAddRequest.FailureNodeId.Value != -1)
        {
            var failureNode = await flowNodeRepository.GetByIdAsync(flowNodeAddRequest.FailureNodeId.Value);
            if (failureNode == null)
            {
                return -1;
            }
        }

        return await flowNodeRepository.InsertAsync(flowNodeAddRequest);
    }

    public async Task<int> UpdateFlowNode(FlowNodeUpdateRequest flowNodeUpdateRequest)
    {
        if (flowNodeUpdateRequest.Id <= 0)
        {
            return -1;
        }

        switch (flowNodeUpdateRequest.ProcessingType)
        {
            case NodeProcessingType.Dept:
                var department = await departmentRepository.GetByIdAsync(flowNodeUpdateRequest.ProcessingId);
                if (department == null)
                {
                    return -1;
                }

                break;
            case NodeProcessingType.Teacher:
                var teacher = await teacherRepository.GetByIdAsync(flowNodeUpdateRequest.ProcessingId);
                if (teacher == null)
                {
                    return -1;
                }

                break;
            default:
                throw new ArgumentOutOfRangeException();
        }

        switch (flowNodeUpdateRequest.SuccessType)
        {
            case NodeSuccessType.OnlyOne:
                break;
            case NodeSuccessType.All:
                break;
            case NodeSuccessType.Number:
                if (flowNodeUpdateRequest.SuccessConfig is not > 0)
                {
                    return -1;
                }

                break;
            case NodeSuccessType.PCT:
                if (flowNodeUpdateRequest.SuccessConfig is not > 0)
                {
                    return -1;
                }

                if (flowNodeUpdateRequest.SuccessConfig > 100)
                {
                    return -1;
                }

                break;
            default:
                throw new ArgumentOutOfRangeException();
        }

        if (flowNodeUpdateRequest.SuccessNodeId != null && flowNodeUpdateRequest.SuccessNodeId.Value != -1)
        {
            var successNode = await flowNodeRepository.GetByIdAsync(flowNodeUpdateRequest.SuccessNodeId.Value);
            if (successNode == null)
            {
                return -1;
            }
        }

        if (flowNodeUpdateRequest.FailureNodeId != null && flowNodeUpdateRequest.FailureNodeId.Value != -1)
        {
            var failureNode = await flowNodeRepository.GetByIdAsync(flowNodeUpdateRequest.FailureNodeId.Value);
            if (failureNode == null)
            {
                return -1;
            }
        }

        return await flowNodeRepository.UpdateAsync(flowNodeUpdateRequest) ? 1 : -1;
    }

    public async Task<int> DeleteFlowNodeByIds(List<long> ids)
    {
        return await flowNodeRepository.DeleteByIdsAsync(ids) ? 1 : -1;
    }
}